#include "WorldModel.h"
#include "WorldEntity.h"
#include "EntityPlayer.h"
#include "EntityDecor.h"
#include "EntityProjectile.h"
#include "EntityExplosion.h"
#include "EntityEnemy.h"
#include "Engine.h"

#include "ComponentManager.h"

#include <iostream>
using namespace std;

#define USE_SCENE

CWorldModel::CWorldModel(): m_quitGame(false), m_pauseGame(false), m_idTexturePauseScreen(-1)
{

}

CWorldModel::~CWorldModel()
{
	for(vector<CWorldEntity*>::iterator i=m_vectorEntity.begin(); i<m_vectorEntity.end(); i++)
	{
		delete *i;
		*i=0;
	}
}

void CWorldModel::doUpdate(void)
{
	if(!m_pauseGame)
	{
		//apply the actions sent by the user interface
		for(vector<CWorldEntity*>::iterator i=m_vectorEntity.begin(); i<m_vectorEntity.end(); i++)
		{
			if((*i)->getActive())
				(*i)->doUpdate();
		}
	}
}

void CWorldModel::doRender(void)
{
	if(!m_pauseGame)
	{
		for(vector<CWorldEntity*>::iterator i=m_vectorEntity.begin(); i<m_vectorEntity.end(); i++)
		{
			if((*i)->getActive())
				(*i)->doRender();
		}
		CM.UI().displayHUD();
	}
	else
		CM.VISU().displayTexture(m_idTexturePauseScreen, CVector2i(0, 0));
}

void CWorldModel::createEntityPlayer(const CVector2i& startPosition, int speed, int idAnimWalkRight,
		int idAnimWalkLeft, int indexAnimIdleRight, int indexAnimIdleLeft, int indexAnimJumpRight, int indexAnimJumpLeft,
		int indexAnimAttackRight, int indexAnimAttackLeft, int healthPoint)
{
	CWorldEntity* newPlayerEntity = new CEntityPlayer(startPosition, speed, idAnimWalkRight, idAnimWalkLeft, 
		indexAnimIdleRight, indexAnimIdleLeft, indexAnimJumpRight, indexAnimJumpLeft, indexAnimAttackRight, 
		indexAnimAttackLeft);
	newPlayerEntity->setHealthPoint(healthPoint);
	m_indexPlayer=m_vectorEntity.size();
	m_vectorEntity.push_back(newPlayerEntity);
}

void CWorldModel::createEntityDecor(int indexGfx, const CVector2i& startPosition)
{

	CWorldEntity* newDecorEntity = new CEntityDecor(indexGfx, startPosition);
	m_vectorEntity.push_back(newDecorEntity);
}

CEntityProjectile* CWorldModel::createEntityProjectile(int indexTexture, int indexSprite, const CVector2i& position, int speed)
{
	CEntityProjectile* newProjectile = new CEntityProjectile(indexTexture, indexSprite, position, true, speed);
	m_vectorEntity.push_back(newProjectile);
	return newProjectile;
}

CEntityEnemy* CWorldModel::createEntityEnemy(const CVector2i& initialPosition, int range, int animWalkLeft, 
		int animWalkRight, int hp, int damagePoint, int speed)
{
	CEntityEnemy* newEnemy = new CEntityEnemy(initialPosition, range, animWalkLeft, animWalkRight, hp, damagePoint, speed);
	m_vectorEntity.push_back(newEnemy);
	return newEnemy;
}

CEntityExplosion* CWorldModel::createEntityExplosion(int indexAnimation, const CVector2i& position, int sound)
{
	CEntityExplosion* newEntityExplosion = new CEntityExplosion(indexAnimation, position, sound);
	m_vectorEntity.push_back(newEntityExplosion);
	return newEntityExplosion;
}

void CWorldModel::addAction(eAction newAction)//a modifier
{
	if(m_pauseGame && newAction != ePause)
		return;

	CEntityPlayer* currentPlayer = (CEntityPlayer*)m_vectorEntity[m_indexPlayer];

	switch(newAction)
	{
		case eNoAction:
			break;

		case eMoveLeft:
			currentPlayer->addAction(eMoveLeft);
			break;

		case eMoveRight:
			currentPlayer->addAction(eMoveRight);
			break;

		case eJump:
			//
			currentPlayer->addAction(eJump);
			break;

		case eAttack:
			currentPlayer->addAction(eAttack);
			break;

		case ePause:
			m_pauseGame = !m_pauseGame;
			break;

		case eVolumeUp:
			//
			break;

		case eVolumeDown:
			//
			break;

		case eQuit:
			m_quitGame=true;
		default:
			break;
	}
}

void CWorldModel::fillQuadTree(void)
{
	for(vector<CWorldEntity*>::iterator i=m_vectorEntity.begin(); i!=m_vectorEntity.end(); i++)
		CM.SCENE().addEntity(*i);
}

CWorldEntity* CWorldModel::checkCollision(CWorldEntity* entity)
{
#ifdef _DEBUG
	CM.PROFILER().startCount("Collision Test");
#endif
	vector<CWorldEntity*>* previousArray = 0;
	int indexLeaf=0;
	bool over = false;
	vector<CWorldEntity*>* sceneArray = 0;

	while(!over)//while all the vector have not been iterated
	{
#ifdef USE_SCENE
		//get a vector
		sceneArray = CM.SCENE().getVectorOfArea(entity, indexLeaf);

		if(sceneArray == 0)//if the array has been checked already
		{
			#ifdef _DEBUG
			CM.PROFILER().endCount("Collision Test");
			#endif
			return 0;
		}
#else
		sceneArray = &m_vectorEntity;
		over = true;
#endif
		//go throught the entities
		for(vector<CWorldEntity*>::iterator i=sceneArray->begin(); i<sceneArray->end(); i++)
		{
			//if the entity is collidable and not the one checked with
			if((*i)->getCanCollide() && (*i)!=entity && entity->getSide() != (*i)->getSide() && (*i)->getActive())
			{
				//check collision
				if(entity->isCollidingWith(*i))
				{
					#ifdef _DEBUG
						CM.PROFILER().endCount("Collision Test");
					#endif
					return *i;
				}
			}
		}
		indexLeaf++;
		previousArray = sceneArray;
	}
#ifdef _DEBUG
	CM.PROFILER().endCount("Collision Test");
#endif
	return 0;
}

bool CWorldModel::quitGame(void)
{
	return m_quitGame;
}

void CWorldModel::scrollWorld(const CVector2i& scroll)
{
	for(vector<CWorldEntity*>::iterator i=m_vectorEntity.begin(); i!=m_vectorEntity.end(); i++)
		(*i)->scrollEntity(scroll);
		//(*i)->setPosition((*i)->getPosition() + scroll);

	CM.SCENE().scrollBoundaries(scroll);
}

int CWorldModel::getHealthPlayer(void)const
{
	return m_vectorEntity[m_indexPlayer]->getHealthPoint();
}

void CWorldModel::setPauseScreen(int idTexturePauseScreen)
{
	m_idTexturePauseScreen = idTexturePauseScreen;
}
